
# -*- coding: utf-8 -*-

import cv2
import hashlib
import numpy as np
from models.User import User
from config import Config

FaceRecognizer = None

def loadImagesFromDatabase():
	images, users = [],[]
	for user in User.select():
		for image in user.image_set:
			try:
				cv_image = cv2.imread(image.path, cv2.IMREAD_GRAYSCALE)
				if cv_image is not None:
					cv_image = cv2.resize(cv_image, (100,100))
					images.append(np.asarray(cv_image, dtype=np.uint8))
					users.append(user.id)
			except IOError, (errno, strerror):
				print "Error al leer la imagen {0}: {1}".format(errno, strerror)
			except Exception, (errno, strerror):
				print "Error al leer la imagen {0}: {1}".format(errno, strerror)
	return images, np.asarray(users)

def trainModel():
	try:
		global FaceRecognizer
		images, Users = loadImagesFromDatabase()
		FaceRecognizer = cv2.createLBPHFaceRecognizer()
		#model = cv2.createFisherFaceRecognizer()
		#model = cv2.createEigenFaceRecognizer()
		FaceRecognizer.train(images,Users)
		FaceRecognizer.save(Config.TRAINING_MODEL_FILENAME)
	finally:
		Config.STATE_TRAINING_MODEL = False

def predict(cv_image):
	faces = detect_faces(cv_image)
	result = None
	if len(faces) > 0:
		cropped = to_grayscale(crop_faces(cv_image, faces))
		resized = cv2.resize(cropped, (100,100))
		prediction = FaceRecognizer.predict(resized)
		user = User.get(User.id == prediction[0])
		result = {
			'face': {
				'id': user.id,
				'name': user.name,
				'username': user.username,
				'hash': hashlib.md5("$$%s##" % user.username).hexdigest(),
				'distance': prediction[1],
				'coords': {
					'x': str(faces[0][0]),
					'y': str(faces[0][1]),
					'width': str(faces[0][2]),
					'height': str(faces[0][3])
				}
			 }
		}
	return result

def detect(img, cascade):
	gray = to_grayscale(img)
	rects = cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=4, minSize=(30, 30), flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
	if len(rects) == 0:
		return []
	return rects

def detect_faces(img):
	cascade = cv2.CascadeClassifier(Config.OPENCV_CASCADE_CLASSIFIER)
	return detect(img, cascade)

def to_grayscale(img):
	gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
	gray = cv2.equalizeHist(gray)
	return gray

def contains_face(img):
	return len(detect_faces(img)) > 0

def save(path, img):
	cv2.imwrite(path, img)

def crop_faces(img, faces):
	for face in faces:
		x, y, h, w = [result for result in face]
		return img[y:y+h,x:x+w]
